package element.synt;

import element.ast.AstNode;
import element.ast.DopNode;
import element.ast.PrimNode;
import element.base.Synt;
import element.base.TreeNode;
import element.base.Word;
import intermediate_representation.AssignRP;
import intermediate_representation.CjumpRP;
import intermediate_representation.JumpRP;
import table.InterCodeTable;

public class EqExp extends Synt {
    public AstNode toAst() {
        if (this.isConst()) {
            return new PrimNode(this.calcu());
        }
        TreeNode node0 = this.getNodes().get(0);
        if (node0 instanceof RelExp) {
            return ((RelExp) node0).toAst();
        } else {
            RelExp right = (RelExp) this.getNodes().get(2);
            EqExp left = (EqExp) node0;
            String op = ((Word) this.getNodes().get(1)).getContent();
            AstNode leftNode = left.toAst();
            AstNode rightNode = right.toAst();
            return new DopNode(op, leftNode, rightNode);
        }
    }

    public int calcu() {
        TreeNode node0 = this.getNodes().get(0);
        if (node0 instanceof RelExp) {
            return ((RelExp) node0).calcu();
        } else {
            RelExp right = (RelExp) this.getNodes().get(2);
            EqExp left = (EqExp) node0;
            String op = ((Word) this.getNodes().get(1)).getContent();
            int leftvalue = left.calcu();
            int rightvalue = right.calcu();
            if (op.equals("==")) {
                if (leftvalue == rightvalue) {
                    return 1;
                } else {
                    return 0;
                }
            } else {
                if (leftvalue != rightvalue) {
                    return 1;
                } else {
                    return 0;
                }
            }
        }
    }

    public boolean isConst() {
        TreeNode node0 = this.getNodes().get(0);
        if (node0 instanceof RelExp) {
            return ((RelExp) node0).isConst();
        } else {
            RelExp right = (RelExp) this.getNodes().get(2);
            EqExp left = (EqExp) node0;
            return left.isConst() && right.isConst();
        }
    }

    public void Jump(String successLabel, String failureLabel, boolean need) {
        if (isConst()) {
            int bol = this.calcu();
            if (need) {
                if (bol != 0) {
                    JumpRP jumpRP = new JumpRP(successLabel);
                    InterCodeTable.addCode(jumpRP);
                }
            } else {
                if (bol == 0) {
                    JumpRP jumpRP = new JumpRP(failureLabel);
                    InterCodeTable.addCode(jumpRP);
                }
            }
        } else {
            TreeNode node0 = this.getNodes().get(0);
            int nowindex = InterCodeTable.regindex;
            if (node0 instanceof RelExp) {
                ((RelExp) node0).Jump(successLabel, failureLabel, need);
            } else {
                CjumpRP cjumpRP = null;
                RelExp right = (RelExp) this.getNodes().get(2);
                EqExp left = (EqExp) this.getNodes().get(0);
                String op = ((Word) this.getNodes().get(1)).getContent();
                left.toInterRP();
                String leftcond = InterCodeTable.nowVar;
//                InterCodeTable.pushvar();
                right.toInterRP();
                String rightcond = InterCodeTable.nowVar;
                if (op.equals("==")) {
                    if (need) {
                        cjumpRP = new CjumpRP(leftcond, rightcond, "beq", successLabel);
                    } else {
                        cjumpRP = new CjumpRP(leftcond, rightcond, "bne", failureLabel);
                    }
                } else if (op.equals("!=")) {
                    if (need) {
                        cjumpRP = new CjumpRP(leftcond, rightcond, "bne", successLabel);
                    } else {
                        cjumpRP = new CjumpRP(leftcond, rightcond, "beq", failureLabel);
                    }
                }
                InterCodeTable.addCode(cjumpRP);
            }
            InterCodeTable.regindex = nowindex;
        }
    }

    public void toInterRP() {
        if (isConst()) {
            int bol = this.calcu();
            InterCodeTable.pushvar();
            AssignRP assignRP = new AssignRP(InterCodeTable.nowVar, String.valueOf(bol));
            InterCodeTable.addCode(assignRP);
        } else {
            AstNode astNode = this.toAst();
            astNode.tointerRP();
        }
    }
}
